<?php

namespace App\Http\Controllers;


use App\Models\User;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Crypt;

class Controller extends BaseController
{
    use AuthorizesRequests, DispatchesJobs, ValidatesRequests;

    protected $myUser;
    protected $myUid;

    /**
     * Request实例
     * @var \Illuminate\Http\Request $request
     */
    protected $request;

    protected $optLogic;

    /**
     * 统一初始化 方便以后的统一操作
     *
     * @param \Illuminate\Http\Request $request
     * @return \Illuminate\Http\Response
     */
    public function __construct(Request $request)
    {
        // 配置信息
        $this->request = $request;
        define('LARAVEL_TIME', time());
        define('SUCCESS_CODE', 200);
        define('ERROR_CODE', 400);  // 失败时返回
        define('LOGIN_ERROR', 100); // 需要重新登录的

        // TODO 暂时没有加密解密，只有一般操作
        // 不加密：必须传递 参数 U4TIRP87hGoJhcyM，且值为mZwTzXgOawVV1GJJ
        //$request_is_encode = $request->header('U4TIRP87hGoJhcyM');
        $request_is_encode = 'mZwTzXgOawVV1GJJ'; // 默认没有加密， 需要加密则注释
        // 如果传递参数不对或者没有传递该参数，则表示传递的参数是加密的，需要解密
        if($request_is_encode != 'mZwTzXgOawVV1GJJ'){
            define('IS_ENCODE', 1); // 设置为加密状态
            // 将传递过来的参数，进行解密操作
            $contents1 = $request->all();
            $contents2 = $request->input('contents');
            $contents2 = json_decode($this->decode($contents2), true);
            $contents  = empty($contents2) ? $contents1 : array_merge($contents1, $contents2);
        } else{
            define('IS_ENCODE', 0); // 设置状态为不加密
            $contents = $request->all();
        }


        //$this->optLogic($contents);
        $this->optLogic = (new \App\Service\Option())->setApp($this->request);
        // 获取用户信息
        //$this->myUser();

        // 控制器初始化
        $this->initialize();
    }

    // 初始化
    protected function initialize()
    {
    }

    // 实例化 逻辑option
    protected function optLogic()
    {
        if(empty($this->optLogic)){
            $this->optLogic = (new \App\Service\Option())->setApp($this->request);
        }

        return $this->optLogic;
    }

    // 获取用户以及权限
    protected function myUser()
    {
        $option = $this->optLogic();
        $info   = $option->token();
        if($info === false){
            $option->throwIf(empty($user), $option->getError(), $option->getCode());
        }
        if(empty($info)){
            return $info;
        }
        // 组合
        $info['uid']  = $info['id'];
        $this->myUid  = $info['id'];
        $this->myUser = $info;

        return $info;
    }

    ##########################################################################################
    ## 返回数据（这里最好转到控制器操作）

    // 直接输出返回数据
    // 与output区别：output输出，前端多一个字段，用于判断返回的参数是否加密
    protected function message($message, $code = SUCCESS_CODE, $data = [])
    {
        $data = empty($data) ? [] : $data;
        if(IS_ENCODE){
            $data = $this->encode($data);
        }
        $json = [
            'msg'  => $message,
            'code' => $code,
            'data' => $data,
            // 重新设置页面token
            //'_page_token' => $this->_page_token,
        ];
        $this->json($json);
    }

    // 接口处理成功时返回
    protected function success($data = [], string $message = '操作成功')
    {
        $data = empty($data) ? [] : $data;
        if(IS_ENCODE){
            $data = $this->encode($data);
        }
        $json = [
            'msg'  => $message,
            'code' => SUCCESS_CODE,
            'data' => $data,
            // 重新设置页面token
            //'_page_token' => $this->_page_token,
        ];

        return $this->json($json);
    }

    // 接口处理失败时调用
    protected function error(string $message = '操作失败', array $data = [], int $code = ERROR_CODE)
    {
        $data = empty($data) ? [] : $data;
        if(IS_ENCODE){
            $data = $this->encode($data);
        }
        $json = [
            'msg'  => $message,
            'code' => $code,
            'data' => $data,
            // 重新设置页面token
            //'_page_token' => $this->_page_token,
        ];

        return $this->json($json);
    }

    // 输出JSON数据
    protected function json($data, $is_encode = IS_ENCODE)
    {
        $host_name = isset($_SERVER['HTTP_ORIGIN']) ? $_SERVER['HTTP_ORIGIN'] : '*';
        $options   = [];
        $header    = [
            'Access-Control-Allow-Origin'      => $host_name,
            'Access-Control-Allow-Credentials' => 'true',
            'Access-Control-Allow-Headers'     => 'Origin,X-Requested-With,Content-Type,Accept,Authorization',
            'Access-Control-Allow-Methods'     => 'POST,GET,OPTIONS',
        ];
        if($is_encode){
            //$data = ['data' => $this->encode($data)];
        } else{
            $data['access'] = 1; //不加密
        }

        return response()->json($data);
        //return Response::create($data, 'json', 200)->header($header)->options($options);
    }

    // 加密
    protected function encode($data)
    {
        $data = is_array($data) ? json_encode($data, JSON_UNESCAPED_UNICODE) : $data;

        // 加密配置
        $iv   = '';
        $type = 'DES-ECB';
        $type = 'AES-128-CBC';
        $conf = Config::get('encrypt');
        $key  = substr($conf['key'], 0, 24);
        if($type == 'AES-128-CBC' || $type == 'AES-192-CBC'){
            //$iv = '1234567812345678';
            $iv = substr($conf['iv'], 0, 16);
        }

        $str = openssl_encrypt($data, $type, $key, 0, $iv);

        return base64_encode($str);
    }

    // 解密
    protected function decode($str)
    {
        if(empty($str)){
            return '';
        }


        $string = base64_decode($str);

        // 加密配置
        $iv   = '';
        $type = 'DES-ECB';
        $type = 'AES-128-CBC';
        $conf = Config::get('encrypt');
        $key  = substr($conf['key'], 0, 24);
        if($type == 'AES-128-CBC' || $type == 'AES-192-CBC'){
            //$iv = '1234567812345678';
            $iv = substr($conf['iv'], 0, 16);
        }


        return openssl_decrypt($string, $type, $key, 0, $iv);
        //return openssl_decrypt($string, $type, $key, OPENSSL_RAW_DATA, $iv);
    }

}


